<template>
  <div class="dryrun">
    <el-dialog
      v-bind="$attrs"
      width="1000px"
      v-on="$listeners"
      @close="handleClose"
      @open="handleOpen"
    >
      <template #title>
        <div>
          <span class="mr-2">{{ $t('flyparam.batch_operation') }}</span>
          <el-tooltip>
            <template #content>
              <div
                class="text-md"
                v-html="$t('flyparamter.batch_operation_help')"
            /></template>
            <i class="el-icon-question" />
          </el-tooltip></div
      ></template>
      <div class="dryrun-button-group">
        <button
          class="dryrun-header-button"
          :class="{ active: operationType === 1 }"
          @click="() => handleOperationChange(1)"
        >
          <svg-icon icon-class="upgrade" class-name="mr-2" />{{
            $t('flyparam.update_fields')
          }}
        </button>
        <button
          class="dryrun-header-button"
          :class="{ active: operationType === 2 }"
          @click="() => handleOperationChange(2)"
        >
          <i class="el-icon-delete mr-2" />{{ $t('flyparam.remove_terminal') }}
        </button>
      </div>
      <div>
        <!-- Conditions -->

        <div class="py-3" style="padding-left: 30px">
          <div class="dryrun-condition">
            <h3 class="font-bold mb-3 mr-2">
              {{ $t('flyparam.conditions') }}
              <el-tooltip placement="top">
                <template #content>
                  <div
                    class="text-md"
                    v-html="$t('flyparam.batch_operation_help2')"
                /></template>
                <i class="el-icon-question" />
              </el-tooltip>
            </h3>
            <el-form
              ref="conditionForm"
              :model="conditionForm"
              validate-on-rule-change
              @submit.native.prevent
            >
              <el-row
                v-for="(item, index) in _conditions"
                :key="index"
                class="text-center relative mb-3"
              >
                <el-col>
                  <div class="input-group">
                    <div
                      class="el-select-group"
                      :class="{ boolean: item.valueType === types.BOOLEAN }"
                    >
                      <el-form-item
                        :rules="[
                          {
                            required: true,
                            message: $t('flyparam.required2')
                          }
                        ]"
                        :prop="'conditions.' + index + '.' + 'select'"
                      >
                        <el-select
                          v-if="index === 0"
                          v-model="tableId"
                          disabled
                          size="small"
                          :placeholder="$t('flyparam.select_table')"
                          @change="handleTableIdChange"
                        >
                          <el-option
                            v-for="table in profileTableList"
                            :key="table.id"
                            :label="table.name"
                            :value="table.id"
                          />
                        </el-select>
                        <el-select
                          v-else
                          v-model="item.conditionConnector"
                          size="small"
                          :placeholder="$t('flyparam.select_table')"
                        >
                          <el-option label="AND" :value="1" />
                          <el-option label="OR" :value="2" />
                        </el-select>
                      </el-form-item>
                      <el-form-item
                        :prop="'conditions.' + index + '.' + 'cascader'"
                        :rules="[
                          { required: true, message: $t('flyparam.required2') }
                        ]"
                      >
                        <el-cascader
                          ref="conditionCascader"
                          v-model="item.cascader"
                          v-popover="`condition${index}`"
                          filterable
                          :props="{
                            value: 'paramId',
                            label: 'label',
                            rules: 'rules',
                            referenceType: 'referenceType'
                          }"
                          :options="parameterLabels"
                          @change="
                            (value) => handleCascaderChange(value, item, index)
                          "
                        >
                          <template v-slot="{node,data}">
                            <div v-if="data.disabled" class="flex items-center">
                              <span class="flex-1"> {{ data.label }} </span>
                              <el-tooltip
                                :content="$t('flyparam.dryrun_restricted')"
                                placement="top"
                              >
                                <i
                                  class="el-icon-question"
                                  style="color: #606266"
                                />
                              </el-tooltip>
                            </div>
                            <span v-else>{{ data.label }}</span>
                          </template>
                        </el-cascader>
                      </el-form-item>
                      <el-form-item
                        :prop="'conditions.' + index + '.' + 'conditionMatcher'"
                        :rules="[{ required: true, message: 'Required' }]"
                      >
                        <el-select
                          v-model="item.conditionMatcher"
                          size="small"
                          :placeholder="$t('common.please_select')"
                          @change="
                            () => {
                              item.value = ''
                            }
                          "
                        >
                          <el-option
                            v-for="option in conditionOptions[item.valueType] ||
                            conditionOptions.others"
                            :key="option.value"
                            :label="option.label"
                            :value="option.value"
                          />
                        </el-select>
                      </el-form-item>
                    </div>
                    <el-form-item v-if="item.valueType === types.BOOLEAN" />
                    <el-form-item
                      v-else
                      :rules="[
                        {
                          required: item.conditionMatcher !== 3,
                          message: $t('flyparam.required2')
                        }
                      ]"
                      :prop="'conditions.' + index + '.' + 'value'"
                    >
                      <template v-if="item.valueType === types.REFERENCE">
                        <el-select
                          v-if="item.table.tableType === 3"
                          v-model="item.value"
                          v-loadmore="
                            () => handleLoadMoreReference(item, 'conditions')
                          "
                          multiple
                          size="small"
                          class="input-group-right text-left"
                          :loading="valueSelectorLoading"
                          @visible-change="
                            (visible) =>
                              fetchReferenceData(
                                visible,
                                true,
                                item,
                                'conditions'
                              )
                          "
                        >
                          <el-option
                            v-for="value in referenceValues"
                            :key="value.$id[0]"
                            :label="value.$label[0]"
                            :value="value.$id[0]"
                          />
                        </el-select>
                        <el-select
                          v-else
                          v-model="item.value"
                          :popper-append-to-body="false"
                          multiple
                          size="small"
                          class="input-group-right object-table-select"
                          @click.native="
                            (e) =>
                              handleReferenceClick(e, item.id, 'conditions')
                          "
                        />
                      </template>
                      <el-date-picker
                        v-else-if="item.valueType === types.DATE"
                        v-model="item.value"
                        :disabled="item.conditionMatcher === 3"
                        class="input-group-right"
                        :format="item.formatter"
                        :value-format="item.formatter"
                        type="date"
                        size="small"
                      />
                      <el-date-picker
                        v-else-if="item.valueType === types.DATETIME"
                        v-model="item.value"
                        :disabled="item.conditionMatcher === 3"
                        class="input-group-right"
                        :format="item.formatter"
                        :value-format="item.formatter"
                        type="datetime"
                        size="small"
                      />
                      <el-time-picker
                        v-else-if="item.valueType === types.TIME"
                        v-model="item.value"
                        :disabled="item.conditionMatcher === 3"
                        :format="item.formatter"
                        :value-format="item.formatter"
                        size="small"
                        style="width: 100%"
                      />
                      <el-input
                        v-else-if="item.valueType === types.FILE"
                        v-model="item.value"
                        :disabled="item.conditionMatcher === 3"
                        readonly
                        size="small"
                        class="input-group-right cursor-pointer"
                        :placeholder="$t('flyparam.choose_file')"
                        @click.native="
                          (e) => handleFileUploadClick(e, item.id, 'condition')
                        "
                      />

                      <el-input
                        v-else
                        v-model="item.value"
                        :disabled="item.conditionMatcher === 3"
                        :placeholder="$t('common.please_input')"
                        size="small"
                        class="input-group-right"
                      />
                    </el-form-item>
                  </div>
                </el-col>
                <a
                  v-if="index > 0"
                  class="icon-btn icon-minus"
                  @click="() => removeCondition(index)"
                  >-</a
                >
                <a
                  v-if="index === 0 && _conditions.length < 5"
                  class="icon-btn icon-add"
                  @click="addCondition"
                  >+</a
                >
              </el-row>
            </el-form>
          </div>
        </div>
        <el-row v-loading="dryrunLoading" class="dryrun-result">
          <template>
            <el-col key="download-button" :span="4">
              <h2 v-show="showResult" class="search-result">Search Result</h2>
            </el-col>
            <el-col
              v-if="showResult"
              key="dryrun-result"
              :span="14"
              class="dryrun-col"
            >
              <div class="flex items-center">
                <div class="flex items-center mr-5">
                  <div class="mr-3">
                    <i class="el-icon-success text-xl text-green-400" />
                  </div>
                  <div class="flex-grow">
                    <span
                      >{{ sucNum + failNum }}
                      {{ $t('flyparam.dryrun_matched') }}</span
                    >
                  </div>
                </div>
                <div v-if="failNum > 0" class="flex items-center mr-5">
                  <div class="mr-3">
                    <i class="el-icon-date text-xl text-blue-400" />
                  </div>
                  <div class="flex-grow">
                    <span
                      >{{ failNum }} {{ $t('flyparam.dryrun_schedule') }}</span
                    >
                  </div>
                </div>
                <div class="dryrun-button__container">
                  <el-tooltip
                    v-if="downloadUrl.length > 0"
                    :content="$t('flyparam.download_result')"
                    placement="top"
                  >
                    <button
                      size="small"
                      class="dryrun-download"
                      @click="download"
                    >
                      <i class="el-icon-download" />
                    </button>
                  </el-tooltip>
                </div>
              </div>
            </el-col>
          </template>
          <el-col :span="showResult ? 6 : 20">
            <div class="flex items-center justify-end">
              <div class="dryrun-button__container">
                <button
                  class="dryrun-dryrun-button"
                  type="primary"
                  @click="() => execDryrun(true)"
                >
                  <i v-if="dryrunLoading" class="el-icon-loading" /><i
                    v-else
                    class="el-icon-search mr-2"
                  />{{ $t('flyparam.match_terminal') }}
                </button>
              </div>
            </div>
          </el-col>
        </el-row>

        <!-- Operations -->
        <div class="mt-5 dryrun-operations" style="padding-left: 30px">
          <h3 v-show="operationType === 1" class="font-bold mb-3">
            {{ $t('common.operation') }}
          </h3>
          <div>
            <el-form
              v-show="showOperations"
              ref="operationForm"
              :model="operationForm"
              validate-on-rule-change
              class="operation-form"
              @submit.native.prevent
            >
              <el-row
                v-for="(item, index) in operations"
                :key="index"
                class="relative mb-3"
              >
                <el-col>
                  <div>
                    <div class="w-full flex items-center">
                      <div class="input-group">
                        <div class="el-select-group">
                          <el-select
                            v-model="tableId"
                            disabled
                            size="small"
                            :placeholder="$t('flyparam.select_table')"
                            @change="handleTableIdChange"
                          >
                            <el-option
                              v-for="table in profileTableList"
                              :key="table.id"
                              :label="table.name"
                              :value="table.id"
                            />
                          </el-select>
                          <el-form-item
                            :prop="'operations.' + index"
                            :rules="[
                              {
                                validator: validateOperationSelect,
                                trigger: 'blur',
                                operationType
                              }
                            ]"
                          >
                            <el-cascader
                              ref="operationCascader"
                              v-model="item.cascader"
                              v-popover="`operation${index}`"
                              filterable
                              :props="{
                                value: 'paramId',
                                label: 'label',
                                rules: 'rules',
                                referenceType: 'referenceType'
                              }"
                              :options="filterSelectedParameter(item)"
                              @change="
                                (value) =>
                                  handleOperationCascaderChange(
                                    value,
                                    item,
                                    index
                                  )
                              "
                            />
                          </el-form-item>
                        </div>
                      </div>
                      <span
                        class="px-3"
                        style="display: inline-block; vertical-align: 10px"
                        >=</span
                      >
                      <el-form-item
                        :prop="'operations.' + index + '.' + 'value'"
                        :rules="
                          item.valueType === 'SN'
                            ? [{ required: true, message: 'Required' }]
                            : item.rules
                        "
                      >
                        <template v-if="item.valueType === types.REFERENCE">
                          <el-select
                            v-if="item.table.tableType === 3"
                            v-model="item.value"
                            v-loadmore="
                              () => handleLoadMoreReference(item, 'operations')
                            "
                            multiple
                            size="small"
                            class="input-group-right"
                            :loading="valueSelectorLoading"
                            @visible-change="
                              (visible) =>
                                fetchReferenceData(
                                  visible,
                                  true,
                                  item,
                                  'operations'
                                )
                            "
                          >
                            <el-option
                              v-for="value in referenceValues"
                              :key="value.id[0]"
                              :label="value.$label[0]"
                              :value="value.$label[0]"
                            />
                          </el-select>
                          <el-select
                            v-else
                            v-model="item.value"
                            multiple
                            size="small"
                            :popper-append-to-body="false"
                            class="input-group-right object-table-select"
                            @click.native="
                              (e) =>
                                handleReferenceClick(e, item.id, 'operations')
                            "
                          />
                        </template>

                        <el-date-picker
                          v-else-if="item.valueType === types.DATE"
                          v-model="item.value"
                          class="input-group-right"
                          :format="item.formatter"
                          :value-format="item.formatter"
                          type="date"
                          size="small"
                        />
                        <el-date-picker
                          v-else-if="item.valueType === types.DATETIME"
                          v-model="item.value"
                          class="input-group-right"
                          :format="item.formatter"
                          :value-format="item.formatter"
                          type="datetime"
                          size="small"
                        />
                        <el-time-picker
                          v-else-if="item.valueType === types.TIME"
                          v-model="item.value"
                          :format="item.formatter"
                          :value-format="item.formatter"
                          size="small"
                          style="width: 100%"
                        />
                        <el-select
                          v-else-if="item.valueType === types.BOOLEAN"
                          v-model="item.value"
                          size="small"
                          class="input-group-right"
                        >
                          <el-option
                            :label="$t('flyparam.true_option')"
                            :value="true"
                          />
                          <el-option
                            :label="$t('flyparam.false_option')"
                            :value="false"
                          />
                        </el-select>
                        <el-input
                          v-else-if="item.valueType === types.FILE"
                          v-model="item.value"
                          readonly
                          size="small"
                          class="input-group-right"
                          :placeholder="$t('flyparam.choose_file')"
                          @click.native="
                            (e) =>
                              handleFileUploadClick(e, item.id, 'operation')
                          "
                        />
                        <el-input
                          v-else
                          v-model="item.value"
                          :placeholder="$t('common.please_input')"
                          size="small"
                          class="input-group-right"
                        />
                      </el-form-item>
                    </div>
                  </div>

                  <a
                    v-if="index > 0"
                    class="icon-btn icon-minus"
                    @click="() => removeOperation(index)"
                    >-</a
                  >
                  <a
                    v-if="index === 0 && operations.length < 10"
                    class="icon-btn icon-add"
                    @click="addOperation"
                    >+</a
                  >
                </el-col>
              </el-row>
            </el-form>
          </div>
        </div>
      </div>
      <template #footer>
        <div>
          <el-button size="small" @click="$emit('update:model-value', false)">{{
            $t('common.cancel')
          }}</el-button>
          <el-button
            type="primary"
            size="small"
            :loading="confirmLoading"
            :disabled="!dryrunReady || sucNum === 0"
            @click="() => execDryrun(false)"
            >{{ $t('common.confirm') }}</el-button
          >
        </div></template
      >

      <select-reference
        append-to-body
        :dryrun="true"
        v-model="selectReferenceVisible"
        :table-id="
          currentItem && currentItem.valueType === types.REFERENCE
            ? currentItem.table.id
            : ''
        "
        :current-item="currentItem"
        :template-id="templateId"
        @confirm="
          (selections, ids) => handleSelectReferenceConfirm(selections, ids)
        "
      />

      <upload-file
        :current-item="currentItem"
        append-to-body
        v-model="uploadFileVisible"
        @confirm="(filePath) => handleFileUploadConfirm(filePath)"
      />
    </el-dialog>
  </div>
</template>

<script>
import {
  dryrun,
  refTableDryrun,
  getReferenceEntryRecord,
  getNestedProfileParameters,
  getReferenceTerminalTableRecord
} from '@/api/parameter'
import SelectReference from './select-reference.vue'
import UploadFile from './upload-file'
import { types } from '../constant'
import {
  validateNumber,
  validateReferenceLength,
  validateString,
  validateOperationSelect,
  validateHex
} from '../validate'
import { i18n } from '@/lang'
import { mouseover, mouseout, valueMap } from '@/directives/ellipsis.js'
import { isObjectArray, parseTime } from '@/utils'

const unwatch = () => {}

let elsyMap = {}

export default {
  name: 'DryRun',
  components: {
    SelectReference,
    UploadFile
  },
  directives: {
    popover: {
      bind(el, binding, vnode) {
        const $el = el.querySelector('.el-input__inner')

        $el.addEventListener(
          'mouseover',
          mouseover.bind(this, $el, binding, vnode),
          false
        )
        $el.addEventListener('mouseout', mouseout, false)
      },
      inserted(el, binding, vnode) {
        const $el = el.querySelector('.el-input__inner')
        const sy = Symbol(vnode)
        $el.sy = sy
        valueMap[sy] = ''
        elsyMap[binding.value] = sy
        console.log(valueMap)
      },
      unbind(el, binding) {
        // todo
        const $el = el.querySelector('.el-input__inner')
        delete valueMap['condition0']
        delete valueMap['operation0']
        delete valueMap[$el.sy]
        el.removeEventListener('mouseover', mouseover)
        el.removeEventListener('mouseout', mouseout)
      }
    }
  },
  inheritAttrs: false,

  props: {
    profileId: String,
    profileTableList: Array,
    referenceTable: Array
  },

  data() {
    return {
      cascader: [],
      options: [],
      types,
      tableId: '',
      activeId: '',
      activeHeaderButton: i18n.t('common.update'),
      parameterLabels: [],
      currentParameter: {},
      referenceValues: [],
      totalReferences: 1,
      referencePage: 1,
      currentType: '',
      currentCondition: {},
      currentOperation: {},
      mapValueType: {},
      globalId: 3,
      sucNum: 0, // dryRun成功的数目
      failNum: '', // dryRun失败的数目,
      dryrunLoading: false, // dryRun按钮是否加载中
      valueSelectorLoading: false, // el-select多选是否在加载中
      confirmLoading: false, // Confirm按钮是否加载中
      selectReferenceVisible: false, // 选择应用表的组件是否显示
      uploadFileVisible: false, // 上传文件组件是否显示
      showOperations: true,
      showResult: false,
      conditionOptions: {
        [types.BOOLEAN]: [
          {
            value: 1,
            label: i18n.t('flyparam.true_option')
          },
          {
            value: 2,
            label: i18n.t('flyparam.false_option')
          }
        ],
        [types.NUMBER]: [
          { value: 3, label: i18n.t('flyparam.not_set') },
          { value: 4, label: '=' },
          { value: 5, label: '!=' },
          { value: 6, label: '<' },
          { value: 7, label: '>' },
          { value: 8, label: '<=' },
          { value: 9, label: '>=' }
        ],
        [types.REFERENCE]: [
          { value: 12, label: i18n.t('flyparam.in') },
          { value: 13, label: i18n.t('flyparam.not_in') }
        ],
        others: [
          {
            value: 3,
            label: i18n.t('flyparam.not_set')
          },
          { value: 10, label: i18n.t('flyparam.matches') },
          {
            value: 11,
            label: i18n.t('flyparam.not_matches')
          }
        ]
      },
      conditions: [
        {
          id: 1,
          select: {},
          value: '',
          active: 1,
          conditionMatcher: '',
          conditionConnector: 1,
          rules: {},
          cascader: [],
          originParamTrace: '',
          selectedReferences: []
        }
      ],
      deleteConditions: [
        {
          id: 1,
          select: {},
          value: '',
          active: 1,
          conditionMatcher: '',
          conditionConnector: 1,
          rules: {},
          cascader: [],
          originParamTrace: '',
          selectedReferences: []
        }
      ],
      operationTypes: [
        {
          value: 1,
          label: i18n.t('flyparam.update_fields')
        },
        {
          value: 2,
          label: i18n.t('flyparam.delete_records')
        }
      ],
      operationType: 1,
      dryrunReady: false,
      operations: [{ id: 2, paramId: '', value: '', select: {} }],
      downloadUrl: '',
      validateConditionSelect(rull, value, callback) {
        if (!value.label) {
          return callback(new Error(i18n.t('flyparam.required2')))
        }
        callback()
      },
      validateOperationSelect
    }
  },
  computed: {
    templateId() {
      return this.$route.params.id
    },
    currentItem() {
      return this[this.currentType]
    },
    conditionForm() {
      return {
        conditions: this._conditions
      }
    },
    operationForm() {
      return {
        operations: this.operations
      }
    },
    _conditions() {
      if (this.operationType === 1) {
        return this.conditions
      } else {
        return this.deleteConditions
      }
    },
    conditionString() {
      return JSON.stringify(this._conditions)
    },
    operationsString() {
      return JSON.stringify(this.operations)
    }
  },

  watch: {
    profileId() {
      this.tableId = this.profileId
      // this.fetchLayoutList()
    },
    // 侦测条件的变化
    conditionString() {
      if (this.dryrunReady) {
        this.showResult = !this.showResult
        this.dryrunReady = false
      }
    }
  },
  mounted() {},
  methods: {
    connectorFilter(val) {
      const connectorValue = {
        1: 'AND',
        2: 'OR'
      }

      return connectorValue[val]
    },
    download() {
      const a = document.createElement('a')
      a.setAttribute('href', this.downloadUrl)
      a.click()
    },
    addCondition() {
      this._conditions.push({
        id: this.globalId++,
        select: {},
        value: '',
        active: 1,
        cascader: [],
        conditionMatcher: '',
        conditionConnector: 1,
        originParamTrace: '',
        selectedReferences: []
      })
    },
    addOperation() {
      this.operations.push({
        id: this.globalId++,
        paramId: '',
        value: '',
        select: {}
      })
    },

    handleFileUploadClick(e, id, type) {
      if (type === 'condition') {
        this.currentType = 'currentCondition'
        this.currentCondition = this._conditions.find((_) => _.id === id)
      } else if (type === 'operation') {
        this.currentType = 'currentOperation'
        this.currentOperation = this.operations.find((_) => _.id === id)
      }
      this.uploadFileVisible = true
    },
    handleFileUploadConfirm(filePath) {
      this[this.currentType].value = filePath
    },
    handleReferenceClick(e, id, type) {
      if (type === 'conditions') {
        this.currentType = 'currentCondition'
        this.currentCondition = this._conditions.find((_) => _.id === id)
      } else if (type === 'operations') {
        this.currentType = 'currentOperation'
        this.currentOperation = this.operations.find((_) => _.id === id)
      }

      // debugger

      const current = this[this.currentType]
      // const current = this[this.currentType].find((_) => _.id === id)
      const table = current.table

      // this[this.currentType] = current

      this.activeId = current.paramId
      if (current) {
        if (table) {
          this.selectReferenceVisible = true
        }
      }
    },
    handleSelectReferenceConfirm(labels, items) {
      // this.currentCondition = this._conditions.find((_) => _.id === id)
      if (this.currentType === 'currentCondition') {
        this[this.currentType].selectedReferences = items.map(
          (i) => i.id.split('-')[1]
        )
      }
      this[this.currentType].value = labels
    },
    handleConnectorCommand(command, item) {
      item.conditionConnector = command
    },
    fetchLayoutList() {
      getNestedProfileParameters(this.templateId).then((res) => {
        this.parameterLabels = res
          .filter((_) => _.paramPermissionControl === 1)
          .map((_) => {
            let table

            if (_.valueType === 5) {
              const refTable = this.referenceTable.find(
                (table) => table.id === _.refTableId
              )
              if (_.children) {
                _.referenceType = 'terminal'
              } else {
                _.referenceType = 'refTable'
              }
              if (refTable) {
                table = {
                  id: _.refTableId,
                  tableType: refTable.tableType
                }
              }
            }
            return {
              label: _.label,
              valueType: _.valueType,
              disabled: _.isNewParamAndInTask === 1,
              ..._,
              table
            }
          })
      })
    },
    fetchReferenceData(visible, triggerByDropDown, item, type) {
      // TODO: 考虑删除这个if判断
      if (type === 'conditions') {
        this.currentType = 'currentCondition'
      } else if (type === 'operations') {
        this.currentType = 'currentOperation'
      }
      try {
        if (visible) {
          const arr = type === 'conditions' ? this._conditions : this.operations
          const current = arr.find((_) => _.id === item.id)
          const table = current.table

          if (triggerByDropDown) {
            this.referenceValues.splice(0, this.referenceValues.length)
            this.totalReferences = 1
            this.referencePage = 1
            this.valueSelectorLoading = true
          }
          if (this.totalReferences <= this.referenceValues.length) {
            return
          }

          getReferenceEntryRecord(this.templateId, table.id, {
            pageNo: this.referencePage,
            pageSize: 10
          })
            .then((data) => {
              this.valueSelectorLoading = false
              this.totalReferences = data.total
              this.referenceValues.push(...data.items)
            })
            .catch((err) => {
              this.valueSelectorLoading = false
              this.$confirmError(err)
            })
        }
      } catch (err) {
        console.error(err)
      }
    },

    handleLoadMoreReference(item, type) {
      this.referencePage++
      this.fetchReferenceData(true, false, item, type)
    },

    removeCondition(index) {
      this._conditions.splice(index, 1)
    },
    removeOperation(index) {
      this.operations.splice(index, 1)
    },
    handleClose() {
      unwatch()
      elsyMap = []
      Object.assign(this.$data, this.$options.data())
      this.$nextTick(() => {
        this.$refs.conditionForm.clearValidate()
        this.$refs.operationForm.clearValidate()
      })
    },
    handleOpen() {
      this.tableId = this.profileId
      this.fetchLayoutList()
    },
    handleTableIdChange() {
      this.conditions = [
        {
          id: 1,
          select: {},
          value: '',
          active: 1,
          conditionMatcher: '',
          conditionConnector: 1,
          rules: {}
        }
      ]
      this.fetchLayoutList()
      // this.fetchReferenceTable()
    },
    handleParameterLabelChange(parameter, item) {
      item.parameter = parameter
      item.conditionMatcher = ''
      item.value = ''
      item.rules = parameter.rules
      item.paramId = parameter.paramId
    },
    handleOperationChange(val) {
      if (this.operationType !== val) {
        this.$refs.conditionForm.clearValidate()
        this.dryrunReady = false
        this.showResult = false
        this.operationType = val
        if (val === 2) {
          this.showOperations = false
        } else if (val === 1) {
          this.showOperations = true
        }
      }
    },
    handleDateChange(date, item) {
      const formatter = item.formatter.replace(
        /([ymdMHs])+/g,
        (result, key) => {
          const value = key === 'm' ? 'i' : key
          return '{' + value.toLowerCase() + '}'
        }
      )
      item.value = parseTime(date, formatter)
    },
    async execDryrun(isDryRun) {
      let request = null
      let conditionValid = true
      let operationValid = true
      if (this.tableId === this.profileId) {
        request = dryrun
      } else {
        request = refTableDryrun
      }
      this.$refs.conditionForm.validate((valid) => {
        conditionValid = valid
      })

      if (this.operationType === 1 && !isDryRun) {
        this.$refs.operationForm.validate((valid) => {
          operationValid = valid
        })
      }

      if (conditionValid && operationValid) {
        if (isDryRun) {
          this.dryrunLoading = true
        } else {
          this.confirmLoading = true
        }
        const entityConditions = this._conditions.filter(
          (_) => _.valueType === 'SN'
        )

        const paramConditions = this._conditions.filter(
          (_) => _.valueType !== 'SN'
        )

        try {
          const res = await request(this.templateId, this.tableId, {
            tableId: this.tableId,
            paramConditions: paramConditions.map((condition) => {
              let conditionValues = []
              if (condition.valueType === types.REFERENCE) {
                if (condition.table.tableType === 3) {
                  conditionValues = condition.value.map((item) => {
                    return item.split('-')[1]
                  })
                } else {
                  conditionValues = condition.selectedReferences
                }
              } else {
                conditionValues = [condition.value]
              }

              const ret = {
                conditionMatcher: condition.conditionMatcher,
                conditionValues,
                conditionConnector: condition.conditionConnector,
                paramId: condition.paramId,
                valueType: condition.valueType,
                tableId: condition.tableSchemaId
              }
              if (condition.cascader.length > 1) {
                ret.originParamTrace = condition.originParamTrace
              }
              return ret
            }),
            entityConditions: entityConditions.map((_) => ({
              conditionValues: _.value,
              conditionMatcher: _.conditionMatcher,
              conditionConnector: _.conditionConnector
            })),
            operationType: this.operationType,
            operations:
              this.operationType === 1 && !isDryRun
                ? this.operations.map((_) => {
                    const ret = {
                      paramId: _.paramId,
                      values:
                        _.valueType === types.REFERENCE ? _.value : [_.value]
                    }

                    if (_.cascader.length > 1) {
                      ret.originParamTrace = _.originParamTrace
                    }

                    return ret
                  })
                : [],
            isDryRun,
            orgIds: []
          })
          if (isDryRun) {
            this.showResult = true
            this.dryrunReady = true
            this.sucNum = res.sucNum
            this.failNum = res.failNum
            this.downloadUrl = res.url
            this.dryrunLoading = false
          } else {
            this.confirmLoading = false
            this.$emit('update:model-value', false)
            this.$emit('confirm')
            this.$message.success(this.$t('common.message.operation_success'))
          }
        } catch (err) {
          console.error(err)
          if (isDryRun) {
            this.dryrunLoading = false
          } else {
            this.confirmLoading = false
          }
          this.$message.error(err)
        }
      }
    },
    getRules(item) {
      console.log(item)
      const isOperation = arguments[1] === 'operations'
      const label = item.paramLabel
      const rules = {
        [types.HEX]: [
          {
            required: isOperation ? !item.nullable : true,
            message: this.$t('flyparam.required2', { label: label })
          },
          { validator: validateHex.bind(this), maxLength: item.maxLength }
        ],
        [types.NUMBER]: [
          {
            required: isOperation ? !item.nullable : true,
            message: this.$t('flyparam.required2', { label: label }),
            trigger: 'change'
          },
          {
            validator: validateNumber.bind(this),
            trigger: 'change',
            maxLength: item.maxLength
          }
        ],
        [types.REFERENCE]: [
          {
            validator: validateReferenceLength.bind(this),
            maxLength: item.maxLength,
            nullable: item.nullable,
            table: item.table
          }
        ],
        [types.DATE]: [
          {
            required: isOperation ? !item.nullable : true,
            message: this.$t('flyparam.required2', { label: label }),
            trigger: 'change'
          }
        ],
        [types.DATETIME]: [
          {
            required: isOperation ? !item.nullable : true,
            message: this.$t('flyparam.required2', { label: label }),
            trigger: 'change'
          }
        ],
        [types.BOOLEAN]: [
          {
            required: isOperation ? !item.nullable : true,
            message: this.$t('flyparam.required2', { label: label }),
            trigger: 'change'
          }
        ],
        [types.STRING]: [
          {
            required: true,
            message: this.$t('flyparam.required2')
          },
          {
            validator: validateString.bind(this),
            maxLength: item.maxLength
          }
        ],
        default: [
          [
            {
              required: isOperation ? !item.nullable : true,
              message: this.$t('flyparam.required2', { label: label }),
              trigger: 'blur'
            }
          ]
        ]
      }
      console.log(rules[item.valueType])
      return rules[item.valueType] || rules.default
    },
    handleOperationCascaderChange(value, item, index) {
      this.$refs.operationForm.clearValidate(`operations.${index}.value`)
      let checkedNodes = null
      if (this.$refs.operationCascader[index].getCheckedNodes().length < 1) {
        checkedNodes =
          this.$refs.operationCascader[index].panel.getNodeByValue(value)
      } else {
        checkedNodes = this.$refs.operationCascader[index].getCheckedNodes()[0]
      }

      const labels = checkedNodes.text || checkedNodes.pathLabels.join(' / ')

      if (checkedNodes.data.valueType === types.REFERENCE) {
        const refTable = this.referenceTable.find(
          (table) => table.id === checkedNodes.data.refTableSchemaId
        )
        if (refTable) {
          const table = {
            id: checkedNodes.data.refTableSchemaId,
            tableType: refTable.tableType
          }
          this.operations[index].table = table
        }
      }

      this.operations[index].paramId = checkedNodes.data.paramId
      const valueType = checkedNodes.data.valueType

      this.operations[index].valueType = valueType
      this.operations[index].label = labels
      this.operations[index].nullable = checkedNodes.data.nullable
      this.operations[index].rules = this.getRules(
        checkedNodes.data,
        'operations'
      )
      this.operations[index].formatter = checkedNodes.data.formatter
      this.operations[index].conditionMatcher = ''
      this.operations[index].maxLength = checkedNodes.data.maxLength
      this.operations[index].value = ''

      valueMap[elsyMap['operation' + index]] = labels
      if (value && value.length > 1) {
        const arr = value.slice(0, value.length - 1).map((_) => _.split('-')[1])
        const originParamTrace = arr.join('~')
        this.operations[index].originParamTrace = originParamTrace
      } else {
        this.operations.originParamTrace = ''
      }
    },
    handleCascaderChange(value, item, index) {
      const name = this.operationType === 1 ? 'conditions' : 'deleteConditions'
      const conditions = this[name]
      debugger
      this.$refs.conditionForm.clearValidate(`${name}.${index}.value`)
      let checkedNodes = null
      if (this.$refs.conditionCascader[index].getCheckedNodes().length < 1) {
        checkedNodes =
          this.$refs.conditionCascader[index].panel.getNodeByValue(value)
      } else {
        checkedNodes = this.$refs.conditionCascader[index].getCheckedNodes()[0]
      }
      const labels = checkedNodes.text || checkedNodes.pathLabels.join(' / ')
      if (checkedNodes.data.valueType === types.REFERENCE) {
        const refTable = this.referenceTable.find(
          (table) => table.id === checkedNodes.data.refTableSchemaId
        )
        if (refTable) {
          const table = {
            id: checkedNodes.data.refTableSchemaId,
            tableType: refTable.tableType
          }
          conditions[index].table = table
        }
      }

      conditions[index].paramId = checkedNodes.data.paramId
      const valueType = checkedNodes.data.valueType

      conditions[index].valueType = valueType
      conditions[index].tableSchemaId = checkedNodes.data.tableSchemaId
      conditions[index].label = labels
      conditions[index].rules = this.getRules(item)
      conditions[index].formatter = checkedNodes.data.formatter

      conditions[index].conditionMatcher = ''
      conditions[index].value = ''
      conditions[index].selectedReferences = []

      valueMap[elsyMap['condition' + index]] = labels
      console.log(elsyMap)
      console.log(valueMap)
      if (value && value.length > 1) {
        const arr = value.slice(0, value.length - 1).map((_) => _.split('-')[1])
        const originParamTrace = arr.join('~')
        conditions[index].originParamTrace = originParamTrace
      } else {
        conditions.originParamTrace = ''
      }
    },
    // 筛选出还未选择过的参数，防止重复选择
    filterSelectedParameter(operation) {
      this.operation = operation

      const result = []
      const flatArr = []
      // 将嵌套的数组扁平化
      this.operations.map((obj) => {
        if (obj.children) {
          const el = { ...obj, ...{} }
          delete el.children
          flatArr.push(el)
          Object.values(obj.children).map((v, i) => {
            flatArr.push(v)
          })
        } else {
          flatArr.push(obj)
        }
      })

      const ids = flatArr
        .filter((o) => operation.paramId !== o.paramId)
        .map((o) => o.paramId)

      this.parameterLabels.forEach((item, index) => {
        this.filterFunc(item, result, ids)
      })

      return result
    },

    // TODO: optimize
    filterFunc(item, result, ids) {
      if (item.children && item.children.length > 0) {
        const parent = Object.assign({}, item)
        result.push(parent)
        parent.children = this.filterFunc(item.children, parent, ids)
      } else if (isObjectArray(item) && item.length > 0) {
        return result.children.filter((child) => {
          return !ids.includes(child.paramId)
        })
      } else {
        if (!ids.includes(item.paramId)) {
          result.push(item)
        }
      }
    },
    getReferenceTerminalTableRecord,
    getReferenceEntryRecord
  }
}
</script>

<style lang="scss" scoped>
@import '../styles/dryrun.scss';

@include dryrun;
</style>
